#include "game.h"
#include "ui_game.h"
#include "restart.h"

extern int offensiveMovePlayer;

game::game(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::game)
{
    initui();
    initpainter();
    initgame();
}

game::~game()
{
    delete ui;
}

void game::initui(){
    ui->setupUi(this);
    QPalette pal(this->palette());
    QFont ft;
    this->setWindowTitle("五子棋");
    pal.setColor(QPalette::Background, QColor("#F9D65B"));
    this->setAutoFillBackground(true);
    this->setPalette(pal);
    this->setFixedSize(1000,800);
    ui->lcdNumber->setDigitCount(3);
    ui->lcdNumber->setSegmentStyle(QLCDNumber::Flat);
    ui->label_4->resize(40,100);
    ui->label_4->setStyleSheet("color:red;");
    ft.setPointSize(14);
    ui->label_4->setFont(ft);
}

void game::initgame(){
    table=(chessman*)malloc((SIZE)*(SIZE)*sizeof(chessman));
    for(int i=0;i<SIZE*SIZE;i++){
        table[i].type=chessmanType::none;
    }
    chessPlayer=offensiveMovePlayer;
}

void game::initpainter(){
    setMouseTracking(true);
    painter=new QPainter;
    painter->setRenderHint(QPainter::Antialiasing, true);
}

void game::paintEvent(QPaintEvent *)
{
    painter->begin(this);
    qDebug("MainOffensiveMovePlayer:%d",offensiveMovePlayer);

    painter->setPen(QPen(Qt::black,2,Qt::SolidLine));
    painter->setBrush(QBrush(Qt::black,Qt::SolidPattern));
    painter->drawEllipse(WIDTH*(SIZE+0.65)+20,yChessman,0.7*WIDTH,0.7*WIDTH);

    painter->setPen(QPen(Qt::white,2,Qt::SolidLine));
    painter->setBrush(QBrush(Qt::white,Qt::SolidPattern));
    painter->drawEllipse(WIDTH*(SIZE+2.65)+20,yChessman,0.7*WIDTH,0.7*WIDTH);

    painter->setPen(QPen(Qt::red,2,Qt::SolidLine));
    painter->setBrush(QBrush(Qt::red,Qt::SolidPattern));

    qDebug("%d",chessmanoffset);
    if(chessPlayer==playerblack){
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset-15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+selectXoffset-5,selectY+0.5*WIDTH-15);
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset-15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+selectXoffset-15,selectY+0.5*WIDTH-5);
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset+15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+selectXoffset+5,selectY+0.5*WIDTH+15);
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset+15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+selectXoffset+15,selectY+0.5*WIDTH+5);

        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset-15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+selectXoffset-5,selectY+0.5*WIDTH+15);
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset-15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+selectXoffset-15,selectY+0.5*WIDTH+5);
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset+15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+selectXoffset+5,selectY+0.5*WIDTH-15);
        painter->drawLine(WIDTH*(SIZE+1.15)+selectXoffset+15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+selectXoffset+15,selectY+0.5*WIDTH-5);

    }else{
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-5,selectY+0.5*WIDTH-15);
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-15,selectY+0.5*WIDTH-5);
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+5,selectY+0.5*WIDTH+15);
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+15,selectY+0.5*WIDTH+5);

        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-5,selectY+0.5*WIDTH+15);
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-15,selectY+0.5*WIDTH+15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset-15,selectY+0.5*WIDTH+5);
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+5,selectY+0.5*WIDTH-15);
        painter->drawLine(WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+15,selectY+0.5*WIDTH-15,WIDTH*(SIZE+1.15)+chessmanoffset+selectXoffset+15,selectY+0.5*WIDTH-5);
    }

    painter->setPen(QPen(Qt::darkGreen,2,Qt::SolidLine));
    for(int i=0;i<LINES+1;i++)
    {
        painter->drawLine(Start,Start+WIDTH*i,Start+WIDTH*LINES,Start+WIDTH*i);
        painter->drawLine(Start+WIDTH*i,Start,Start+WIDTH*i,Start+WIDTH*LINES);
    }

        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j< SIZE; j++) {
                chessman ch = get(j, i);
                if (ch.type == chessmanType::none) {
                    printf("- ");
                }
                else if (ch.type == chessmanType::black) {
                    printf("-B");
                    painter->setPen(QPen(Qt::black,2,Qt::SolidLine));
                    painter->setBrush(QBrush(Qt::black,Qt::SolidPattern));
                    painter->drawEllipse((j-0.35)*WIDTH+20,(i-0.35)*WIDTH+20,0.7*WIDTH,0.7*WIDTH);
                }
                else {
                    printf("-W");
                    painter->setPen(QPen(Qt::white,2,Qt::SolidLine));
                    painter->setBrush(QBrush(Qt::white,Qt::SolidPattern));
                    painter->drawEllipse((j-0.35)*WIDTH+20,(i-0.35)*WIDTH+20,0.7*WIDTH,0.7*WIDTH);
                }
            }
            printf("\n");
        }
        printf("\n");
    if(gamemode==started){
        if(drawChess){
            if(chessPlayer==playerblack){
                painter->setPen(QPen(Qt::red,2,Qt::SolidLine));
                painter->setBrush(QBrush(Qt::black,Qt::SolidPattern));
                painter->drawEllipse((mouseX-0.35)*WIDTH+20,(mouseY-0.35)*WIDTH+20,0.7*WIDTH,0.7*WIDTH);
            }else{
                painter->setPen(QPen(Qt::red,2,Qt::SolidLine));
                painter->setBrush(QBrush(Qt::white,Qt::SolidPattern));
                painter->drawEllipse((mouseX-0.35)*WIDTH+20,(mouseY-0.35)*WIDTH+20,0.7*WIDTH,0.7*WIDTH);
            }
            drawChess=false;
        }
        painter->setPen(QPen(Qt::red,2,Qt::SolidLine));
        //选择框
        if(mouseX>=0 && mouseX< SIZE && mouseY >=0 && mouseY < SIZE){
            painter->drawLine((mouseX+0.5)*WIDTH-15,(mouseY+0.5)*WIDTH-15,(mouseX+0.5)*WIDTH-5,(mouseY+0.5)*WIDTH-15);
            painter->drawLine((mouseX+0.5)*WIDTH-15,(mouseY+0.5)*WIDTH-15,(mouseX+0.5)*WIDTH-15,(mouseY+0.5)*WIDTH-5);
            painter->drawLine((mouseX+0.5)*WIDTH+15,(mouseY+0.5)*WIDTH+15,(mouseX+0.5)*WIDTH+5,(mouseY+0.5)*WIDTH+15);
            painter->drawLine((mouseX+0.5)*WIDTH+15,(mouseY+0.5)*WIDTH+15,(mouseX+0.5)*WIDTH+15,(mouseY+0.5)*WIDTH+5);

            painter->drawLine((mouseX+0.5)*WIDTH-15,(mouseY+0.5)*WIDTH+15,(mouseX+0.5)*WIDTH-5,(mouseY+0.5)*WIDTH+15);
            painter->drawLine((mouseX+0.5)*WIDTH-15,(mouseY+0.5)*WIDTH+15,(mouseX+0.5)*WIDTH-15,(mouseY+0.5)*WIDTH+5);
            painter->drawLine((mouseX+0.5)*WIDTH+15,(mouseY+0.5)*WIDTH-15,(mouseX+0.5)*WIDTH+5,(mouseY+0.5)*WIDTH-15);
            painter->drawLine((mouseX+0.5)*WIDTH+15,(mouseY+0.5)*WIDTH-15,(mouseX+0.5)*WIDTH+15,(mouseY+0.5)*WIDTH-5);
        }
    }
    painter->end();
}
void game::mouseMoveEvent(QMouseEvent *event) {
    if(gamemode==started){
        mouseX = (event->x())/WIDTH;
        mouseY = (event->y())/WIDTH;
        qDebug("move: %d %d , t: %d %d",mouseX,mouseY,event->x(),event->y());
        print(mouseX,mouseY);
    }
    update();
}

void game::mouseReleaseEvent(QMouseEvent* event){
    if(gamemode==started && mouseX>=0 && mouseX< SIZE && mouseY >=0 && mouseY < SIZE){
        mouseX = (event->x())/WIDTH;
        mouseY = (event->y())/WIDTH;
        if(chessPlayer==playerblack){
            putSucess=put(mouseX,mouseY,chessmanType::black);
        }else{
            putSucess=put(mouseX,mouseY,chessmanType::white);
        }

        if(putSucess){
            qDebug("player:%d",chessPlayer);
            chessPlayer=!chessPlayer;
            stepX.push_back(mouseX);
            stepY.push_back(mouseY);
            step++;
            ui->lcdNumber->display(step);
        }
        print(mouseX,mouseY);
        winner=iswin();

        qDebug("winner : %d",winner);
        switch (iswin()) {
            case none_win:
                break;
            case white_win:
                qDebug("wWin");
                msg("白方胜利");
                gamemode=gameover;
                break;
            case black_win:
                qDebug("bWin");
                msg("黑方胜利");
                gamemode=gameover;
                break;
            case draw:
                qDebug("draw");
                msg("平局");
                gamemode=gameover;
                break;
        }
    }
    update();
}

chessman game::get(int x, int y){
    int index=y*SIZE+x;
    chessman res;
    res.type = chessmanType::none;

    if (x<0 || x>=SIZE) {
        return res;
    }

    if (y<0 || y>=SIZE) {
        return res;
    }
    return table[index];
}

int game::put(int x,int y,chessmanType type){
    chessman ch = get(x, y);
    if (ch.type != chessmanType::none) {
            return false;
    }

    int index=y*SIZE+x;
    table[index].type=type;
    return true;
}

void game::print(int x, int y){
    int ty=get(x,y).type;
    qDebug("ty:%d",ty);
}

bool game::erase(int x,int y){
    chessman ch=get(x,y);
    int index=y*SIZE+x;

    if(ch.type!=chessmanType::none){
        table[index].type=chessmanType::none;
        return true;
    }
    return false;
}

void game::restartgame(bool changeOffensiveMovePlayer){

    if(changeOffensiveMovePlayer){
        offensiveMovePlayer=!offensiveMovePlayer;
    }
    for(int i=0;i<SIZE*SIZE;i++){
        table[i].type=chessmanType::none;
    }
    step=0;
    stepX.clear();
    stepY.clear();
    chessPlayer=offensiveMovePlayer;
    ui->lcdNumber->display(0);
    gamemode=started;
    update();
}

int game::iswin() {
    chessmanNum=0;
    for (int y = 0; y < SIZE; y++) {
        for (int x = 0; x < SIZE; x++) {
            chessman ch= get(x, y);
            if (ch.type == chessmanType::none) {
                continue;
            }

            chessmanNum++;

            //Horizontal
            chessman h1 = get(x + 1, y);
            chessman h2 = get(x + 2, y);
            chessman h3 = get(x + 3, y);
            chessman h4 = get(x + 4, y);

            //vertical
            chessman v1 = get(x, y + 1);
            chessman v2 = get(x, y + 2);
            chessman v3 = get(x, y + 3);
            chessman v4 = get(x, y + 4);

            //Oblique-Left to Right
            chessman lr1 = get(x + 1, y + 1);
            chessman lr2 = get(x + 2, y + 2);
            chessman lr3 = get(x + 3, y + 3);
            chessman lr4 = get(x + 4, y + 4);

            //Oblique-Right to Left
            chessman rl1 = get(x + 1, y - 1);
            chessman rl2 = get(x + 2, y - 2);
            chessman rl3 = get(x + 3, y - 3);
            chessman rl4 = get(x + 4, y - 4);

            //Horizontal
            if (ch.type == h1.type && ch.type == h2.type &&
                ch.type == h3.type && ch.type == h4.type) {
                if (ch.type == chessmanType::white) {
                    return white_win;
                }
                if (ch.type == chessmanType::black) {
                    return black_win;
                }
            }

            //vertical
            if (ch.type == v1.type && ch.type == v2.type &&
                ch.type == v3.type && ch.type == v4.type) {
                if (ch.type == chessmanType::white) {
                    return white_win;
                }
                if (ch.type == chessmanType::black) {
                    return black_win;
                }
            }

            //Oblique-Left to Right
            if (ch.type == lr1.type && ch.type == lr2.type &&
                ch.type == lr3.type && ch.type == lr4.type) {
                if (ch.type == chessmanType::white) {
                    return white_win;
                }
                if (ch.type == chessmanType::black) {
                    return black_win;
                }
            }

            //Oblique-Right to Left
            if (ch.type == rl1.type && ch.type == rl2.type &&
                ch.type == rl3.type && ch.type == rl4.type) {
                if (ch.type == chessmanType::white) {
                    return white_win;
                }
                if (ch.type == chessmanType::black) {
                    return black_win;
                }
            }
        }
    }

    if(chessmanNum==SIZE*SIZE){
        return draw;
    }
    return none_win;
}

void game::on_pushButton_3_clicked()
{
    QApplication *q;
    q->quit();
}


void game::on_pushButton_2_clicked()
{

    restart *r=new restart();
    connect(r, SIGNAL(sendrestartmsg(bool)), this, SLOT(restartgame(bool)));
    r->show();
}


void game::on_pushButton_clicked()
{
    if(gamemode==started && !stepX.empty() && !stepY.empty()){
        erase(stepX.back(),stepY.back());
        stepX.pop_back();
        stepY.pop_back();
        chessPlayer=!chessPlayer;
        step--;
        ui->lcdNumber->display(step);
        update();
    }else{
        msg("不可悔棋");
        delay_msec(1000);
        clearmsg();
    }
}

void game::msg(QString q){
    ui->label_4->setText(q);
}

void game::setStep(int step)
{
    ui->lcdNumber->display(step);
}

void game::clearmsg(){
    ui->label_4->setText("");
}

void game::delay_msec(unsigned int msec)
{
    QEventLoop loop;
    QTimer::singleShot(msec, &loop, SLOT(quit()));
    loop.exec();
}
